package br.ufpe.cin.mac.middleware.autonomic.monitors;

import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryUsage;

/**
 * This class get System Memory Statistics You nedd tool.jar to use it
 * functions.
 * 
 * @author Rafael Roque
 * @author Osmany
 */
public class MemoryMonitor extends Monitor {

	com.sun.management.OperatingSystemMXBean sunOSMBean;

	public MemoryMonitor() {
		super(MemoryMonitor.class.getName());
		sunOSMBean = null;
		try {
			sunOSMBean = JMXUtil.getOsMBean();
		} catch (IOException e) {
			System.err.println("Problem in " + this.toString()
					+ "\nCould not get OperatingSystemMXBean.");
			System.err.println("StackTrace: \n" + e.getMessage());
		}

	}

	private long getTotalPhysicalMemorySize() {
		if (sunOSMBean == null) {
			return -1;
		}
		return sunOSMBean.getTotalPhysicalMemorySize();

	}

	private float getFreePhysicalMemorySize() {
		if (sunOSMBean == null) {
			return -1;
		}
		return sunOSMBean.getFreePhysicalMemorySize();

	}

	private float getTotalSwapSpaceSize() {
		if (sunOSMBean == null) {
			return -1;
		}
		return sunOSMBean.getTotalSwapSpaceSize();

	}

	private float getFreeSwapSpaceSize() {
		if (sunOSMBean == null) {
			return -1;
		}
		return sunOSMBean.getFreeSwapSpaceSize();

	}

	private float getCommittedVirtualMemorySize() {
		if (sunOSMBean == null) {
			return -1;
		}
		return sunOSMBean.getCommittedVirtualMemorySize();

	}

	private float getHeapMemoryUsage() {
		MemoryUsage u = ManagementFactory.getMemoryMXBean()
				.getHeapMemoryUsage();
		return u.getUsed();
	}

	private float getHeapMemoryMax() {
		MemoryUsage u = ManagementFactory.getMemoryMXBean()
				.getHeapMemoryUsage();
		return u.getMax();
	}

	private float getCommitedMemory() {
		MemoryUsage u = ManagementFactory.getMemoryMXBean()
				.getHeapMemoryUsage();
		return u.getCommitted();
	}

	public String getSummary(float converter) {
		StringBuffer buffer = new StringBuffer();

		// TotalPhysicalMemorySize
		buffer.append("TotalPhysicalMemorySize\t");
		try {
			buffer
					.append(""
							+ ((float) getTotalPhysicalMemorySize() / (float) converter));
		} catch (Exception e) {
			buffer.append("ND");
		}

		// FreePhysicalMemorySize
		buffer.append("\nFreePhysicalMemorySize\t");
		try {
			buffer
					.append(""
							+ ((float) getFreePhysicalMemorySize() / (float) converter));
		} catch (Exception e) {
			buffer.append("ND");
		}

		// TotalSwapSpaceSize
		buffer.append("\nTotalSwapSpaceSize\t");
		try {
			buffer.append(""
					+ ((float) getTotalSwapSpaceSize() / (float) converter));
		} catch (Exception e) {
			buffer.append("ND");
		}

		// FreeSwapSpaceSize
		buffer.append("\nFreeSwapSpaceSize\t");
		try {
			buffer.append(""
					+ ((float) getFreeSwapSpaceSize() / (float) converter));
		} catch (Exception e) {
			buffer.append("ND");
		}

		// Commited Virutal Memory
		buffer.append("\nCommittedVirtualMemorySize\t");
		try {
			buffer
					.append(""
							+ ((float) getCommittedVirtualMemorySize() / (float) converter));
		} catch (Exception e) {
			buffer.append("ND");
		}

		// Current heap size
		buffer.append("\nCurrent heap size\t"
				+ ((float) getHeapMemoryUsage() / (float) converter));

		// Maximum heap size
		buffer.append("\nMaximum heap size\t"
				+ ((float) getHeapMemoryMax() / (float) converter));

		// Committed memory
		buffer.append("\nCommitted memory\t"
				+ ((float) getCommitedMemory() / (float) converter));

		return buffer.toString();

	}

	@Override
	public float getMonitoredValue() {
		return (float) this.getFreePhysicalMemorySize()
				/ (float) this.getTotalPhysicalMemorySize();
	}

	/**
	 * The function main was put here to test the class.
	 * 
	 * @param args
	 */
	public static void main(String args[]) {
		MemoryMonitor monitor = new MemoryMonitor();
		// Show the sumary in MBytes 1048576
		try {
			for (int i = 0; i < 20; i++) {
				System.out.println(monitor.getMonitoredValue());
				Thread.sleep(2000);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
